/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2011.03.31                                          *
 *                                                                       *
 *************************************************************************/

//declaration header
#include "COMMON/info/CommonInfo.h"

//C++ headers
#include <cmath>
#include <stdlib.h>
#include <dirent.h>

//COMMON headers
#include "COMMON/base/Common.h"
//#include "COMMON/base/FreeMAPsVersion.h"
#include "COMMON/base/DefaultParameters.h"
#include "COMMON/tbox/LogMessage.h"
#include "COMMON/tbox/Utilities.h"

namespace FreeMAPs
{

CommonInfo::CommonInfo(
    const std::string& object_name):
    Parent                             ("base_information", object_name),
    d_proj_directory                   (""),
    d_proj_name                        (""),/*
    d_overwrite_exist_file_manner      (WarningLevelType::IGNORE),
    d_do_log_all_nodes                 (false),
    d_do_performance_log               (false),*/
    d_dim                              (-1)/*,
    d_space_degree                     (0),
    d_is_axial_symmetry                (false),
    d_axis_of_symmetry                 (Axis::INVALID_VALUE),
    d_offset_of_axis                   (0.),
    d_do_from_restart                  (false),
    d_restore_number                   (-1),
    d_do_write_restart                 (false),
    d_save_single_restart_file         (true),
    d_restart_interval                 (5),
    d_max_num_time_steps               (0),
    d_global_verbose_level             (2),
    d_use_c_code_to_evaluate_function  (false),
    d_stop_when_numeric_limits_reached (true),
    d_max_ghost_width                  (0),
    d_is_max_ghost_width_decided       (false),
    d_iteration_number                 (0),
    d_start_clock_time                 (static_cast<double>(clock() / CLOCKS_PER_SEC)),
    d_current_clock_time               (d_start_clock_time)*/
{}



CommonInfo::~CommonInfo()
{
    this->clear();
}



void
CommonInfo::clear()
{
    this->update_state (State::BAD);
    /*
        d_overwrite_exist_file_manner      = WarningLevelType::IGNORE;
        d_proj_directory                = ".";
        d_do_log_all_nodes                 = false;
        d_do_performance_log               = false;
        d_proj_name                        = "unnamed";
        d_dim                              = 0;
        d_space_degree                     = 0;
        d_is_axial_symmetry                = false;
        d_axis_of_symmetry                 = Axis::INVALID_VALUE;
        d_offset_of_axis                   = 0.;
        d_do_from_restart                  = false;
        d_restore_number                   = -1;
        d_do_write_restart                 = false;
        d_save_single_restart_file         = true;
        d_restart_interval                 = 5;
        d_global_verbose_level             = 2;
        d_use_c_code_to_evaluate_function  = false;
        d_stop_when_numeric_limits_reached = true;*/
}



std::string
CommonInfo::get_log_file_name() const
{
    return Utilities::get_effective_file_name (d_proj_directory + "/" + d_proj_name + ".log", d_proj_directory);
}



bool
CommonInfo::check_all_info_db (
        const InputDatabase* db)
{
    //dimension
    if( !db->key_exists("dimension") )
    {
        FREEMAPS_ERROR("in \"common_info\", can not find  \"dimension\" \n");
        return false;
    }
    if( !db->is_integer("dimension") )
    {
        FREEMAPS_ERROR("in \"common_info\", \"dimension\" should be interger \n");
        return false;
    }

    //proj_name
    if( !db->key_exists("proj_name") )
    {
        FREEMAPS_ERROR("in \"common_info\", can not find  \"proj_name\" \n");
        return false;
    }
    if( !db->is_string("proj_name") )
    {
        FREEMAPS_ERROR("in \"common_info\", \"proj_name\" should be string \n");
        return false;
    }

    //proj_directory
    if( !db->key_exists("proj_directory") )
    {
        FREEMAPS_ERROR("in \"common_info\", can not find  \"proj_directory\" \n");
        return false;
    }
    if( !db->is_string("proj_directory") )
    {
        FREEMAPS_ERROR("in \"common_info\", \"proj_directory\" should be string \n");
        return false;
    }

    return true;
}



void
CommonInfo::get_from_input (
    const InputDatabase* db)
{
    this->active_verbose_mode (2);

    this->prepare_for_use (db);

    //check parameter
    db->insert_allowable_key ("proj_directory");
    db->insert_allowable_key ("overwrite_exist_file_manner");
    db->insert_allowable_key ("do_log_all_nodes");
    db->insert_allowable_key ("do_performance_log");
    db->insert_allowable_key ("proj_name");
    db->insert_allowable_key ("dimension");
    db->insert_allowable_key ("space_degree");
    db->insert_allowable_key ("is_axial_symmetry");
    db->insert_allowable_key ("axis_of_symmetry");
    db->insert_allowable_key ("offset_of_axis");
    db->insert_allowable_key ("do_from_restart");
    db->insert_allowable_key ("restart_read_directory");
    db->insert_allowable_key ("restore_number");
    db->insert_allowable_key ("do_write_restart");
    db->insert_allowable_key ("save_single_restart_file");
    db->insert_allowable_key ("restart_write_directory");
    db->insert_allowable_key ("restart_interval");
    db->insert_allowable_key ("max_num_time_steps");
    db->insert_allowable_key ("use_c_code_to_evaluate_function");
    db->insert_allowable_key ("stop_when_numeric_limits_reached");

    db->check_allowable_keys ();
    /*
     * build proj_directory
     */
    {
        if( db->key_exists("proj_directory") && db->is_string("proj_directory"))
        {
            db->check_optional_key ("proj_directory", DataType::STRING, true, false);
            d_proj_directory = db->get_string_with_default ("proj_directory", d_proj_directory);
        }
    }


    /*
     * build proj_name
     */
    {
        if( db->key_exists("proj_name") && db->is_string("proj_name"))
        {
            db->check_optional_key ("proj_name", DataType::STRING, true, false);
            d_proj_name = db->get_string_with_default ("proj_name", d_proj_name);
        }
    }

    /*
     * build Dimension
     */
    {
        //dim is not need, when read
        if( db->key_exists("dimension") && db->is_integer("dimension"))
        {
            d_dim = db->get_integer ("dimension");
        }
    }
}



std::ostream&
operator << (
    std::ostream& os,
    const CommonInfo& rhs)
{
    os << "common_info" << RTN_FLAG << "{" << RTN_FLAG;

    os << LogMessage::get_prefix (ONE_TAB) << "proj_directory     = \"" << rhs.d_proj_directory << "\"" << RTN_FLAG;
    os << LogMessage::get_prefix (ONE_TAB) << "proj_name          = \"" << rhs.d_proj_name << '\"'  << RTN_FLAG;
    os << LogMessage::get_prefix (ONE_TAB) << "dimension          = " << rhs.d_dim  << RTN_FLAG;

    os << "}";

    return os;
}

}
